# -*- coding: utf-8 -*-
"""
__mktime__ = '2019/4/13'
__author__ = 'Just'
__filename__ = 'base'
"""
from app.libs.error_code import NotFoundException
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy, BaseQuery
from sqlalchemy import Column, Integer, SmallInteger, inspect, orm
from contextlib import contextmanager


class SQLAlchemy(_SQLAlchemy):
    @contextmanager
    def auto_commit(self):
        """实现自动数据库操作完成关闭 类with open(f)"""
        try:
            yield
            self.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e


class Query(BaseQuery):
    """重载查询类"""
    def filter_by(self, **kwargs):
        """重载 filter_by 过滤status=0的查询"""
        if 'status' not in kwargs.keys():
            kwargs['status'] = 1
        return super(Query, self).filter_by(**kwargs)

    def get_or_404(self, ident, msg=None, error_code=None):
        """重写 get_or_404 查询"""
        rv = self.get(ident)
        if rv is None:
            raise NotFoundException(msg=msg, error_code=error_code)
        return rv

    def first_or_404(self, msg=None, error_code=None):
        """重载 first 方法"""
        rv = self.first()
        if rv is None:
            raise NotFoundException(msg=msg, error_code=error_code)
        return rv


db = SQLAlchemy(query_class=Query)


class BaseModel(db.Model):
    """数据模型基类"""
    __abstract__ = True
    create_time = Column(Integer, default=int(datetime.now().timestamp()), comment='创建时间戳')  # default=int(datetime.now().timestamp()),
    status = Column(SmallInteger, default=1, comment='状态: 1 正常 0 已删除')

    def __getitem__(self, item):
        """重写__getitem__"""
        return getattr(self, item)

    def set_attrs(self, attrs_dict):
        for key, value in attrs_dict.items():
            if not hasattr(self, key) and key != 'id':
                setattr(self, key, value)

    @property
    def create_datetime(self):
        """添加条目, create_time创建时间"""
        if self.create_time:
            return datetime.fromtimestamp(self.create_time)
        else:
            return None

    def delete(self):
        """记录软删除"""
        self.status = 0

    def keys(self):
        """序列化 基础的属性"""
        return self.fields

    def hide(self, *keys):
        """序列化 隐藏不需要的属性"""
        for key in keys:
            self.fields.remove(key)
        return self

    def append(self, *keys):
        """序列化 添加需要的属性"""
        for key in keys:
            self.fields.append(key)
        return self


class MixinJSONSerializer:
    @orm.reconstructor
    def init_on_load(self):
        self._fields = []
        # self._include = []
        self._exclude = []

        self._set_fields()
        self.__prune_fields()

    def _set_fields(self):
        pass

    def __prune_fields(self):
        columns = inspect(self.__class__).columns
        if not self._fields:
            all_columns = set(columns.keys())
            self._fields = list(all_columns - set(self._exclude))

    def hide(self, *args):
        for key in args:
            self._fields.remove(key)
        return self

    def keys(self):
        return self._fields

    def __getitem__(self, key):
        return getattr(self, key)
